package com.invest.infra.excel.utils.annotation;

import com.google.common.collect.Maps;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.reflect.FieldUtils;

import java.lang.reflect.Field;
import java.util.Map;

public class ExcelFieldUtils {

	// key=类型 value=sheet规则
	private static final Map<String,ExcelSheetAnnotation> SHEET_ANN_MAP  =   Maps.newConcurrentMap();
	// key=类型 key=字段名 value=列规则
	private static final Map<String,Map<String,ExcelColumnAnnotation>> COLUMN_ANN_MAP = Maps.newConcurrentMap();
	//key=类型 key=字段名 当前实例的字段
	private static final  Map<String,Map<String,Field>> FIELD_MAP = Maps.newConcurrentMap();

	public static synchronized ExcelSheetAnnotation getClassAnnotation(Class<?> type){
		
		ExcelSheetAnnotation es = SHEET_ANN_MAP.get(type.getName());
		if(es != null){
			return es;
		}
		if(type.isAnnotationPresent(ExcelSheetAnnotation.class)){
			es = type.getAnnotation(ExcelSheetAnnotation.class);
			SHEET_ANN_MAP.put(type.getName(), es);
			initAll(type);
			return es;
		}
		return null;
		
	}
	
	private static synchronized void initAll(Class<?> type){
		
		Map<String,Field> fieldMap = Maps.newHashMap();
		Map<String,ExcelColumnAnnotation> ecAnnotationMap = Maps.newLinkedHashMap();
		
		String className = type.getName();
		FIELD_MAP.put(className, fieldMap);
		COLUMN_ANN_MAP.put(className, ecAnnotationMap);
		
		Field[] fields = type.getDeclaredFields();
		    
		if(ArrayUtils.isNotEmpty(fields)){

			for(Field field : fields){
				if(field.isAnnotationPresent(ExcelColumnAnnotation.class)){
					ExcelColumnAnnotation ex = field.getAnnotation(ExcelColumnAnnotation.class);
					field.setAccessible(true);
					fieldMap.put(field.getName(), field);
					ecAnnotationMap.put(field.getName(), ex);
				}
			}
	  }
	
}
	
	public static void writeFiled(Field field,Object target, Object value){
		
		if(field == null){
			throw new IllegalArgumentException("the field can not be null");
		}
		if(target == null){
			throw new IllegalArgumentException("the target can not be null");
		}
		field.setAccessible(true);
		try {
			FieldUtils.writeField(field, target, value);
		} catch (IllegalAccessException e) {
			throw new IllegalArgumentException("the argument can not be null");
		}
	}

	public static Object getFiledValue(Field field,Object object){
		if(field == null){
			throw new IllegalArgumentException("the field can not be null");
		}
		if(object == null){
			throw new IllegalArgumentException("the target can not be null");
		}

		try {
			field.setAccessible(true);
			return field.get(object);
		} catch (IllegalAccessException e) {
			throw new IllegalArgumentException("the argument can not be null");
		}
	}
	

	
	public static Map<String,ExcelColumnAnnotation>  getFieldAnnotation(Class<?> type){
		
		String className = type.getName();
		if(!COLUMN_ANN_MAP.containsKey(className)){
			initAll(type);
		}
		return COLUMN_ANN_MAP.get(className);
	}
	

	
	public static Field getFiled(Class<?> type,String fieldName){
		
		if(type == null){
			throw new IllegalArgumentException("the type can not be null");
		}
		if(StringUtils.isBlank(fieldName)){
			throw new IllegalArgumentException(fieldName+" the column index can not be null");
		}
			
		String className = type.getName();
		if(!FIELD_MAP.containsKey(className)){
			initAll(type);
		}
		return FIELD_MAP.get(className).get(fieldName);
	}

}
